local extension = Package("a_xianjun_standard")
extension.extensionName = "a_xianjun"

local U = require "packages/utility/utility"

Fk:loadTranslationTable{
  ["a_xianjun_standard"] = "鸿启",
  ["axj"] = "先军",
}

local caocao = General(extension, "axj__caocao", "wei", 4)
local jianxiong = fk.CreateTriggerSkill{
  name = "axj__jianxiong",
  anim_type = "masochism",
  events = {fk.Damage, fk.Damaged},
  can_trigger = function (self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.card and player.room:getCardArea(data.card) == Card.Processing and
      not data.to.dead
  end,
  on_cost = function (self, event, target, player, data)
    if player.room:askForSkillInvoke(player, self.name, nil, "#axj__jianxiong-invoke::"..data.to.id..":"..data.card:toLogString()) then
      self.cost_data = {tos = {data.to.id}}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:moveCardTo(data.card, Card.PlayerHand, data.to, fk.ReasonJustMove, self.name, nil, true, data.to.id)
    if player.dead then return end
    local choices = {"draw1", "Cancel"}
    if not data.to.dead and not data.to:isNude() then
      if data.to ~= player or table.find(player:getCardIds("he"), function (id)
        return not player:prohibitDiscard(id)
      end) then
        table.insert(choices, 2, "axj__jianxiong_discard::"..data.to.id)
      end
    end
    local choice = room:askForChoice(player, choices, self.name)
    if choice == "draw1" then
      player:drawCards(1, self.name)
    elseif choice ~= "Cancel" then
      local card
      if data.to == player then
        card = room:askForDiscard(player, 1, 1, true, self.name, false, nil, "axj__jianxiong-discard::"..data.to.id)
      else
        card = room:askForCardChosen(player, data.to, "he", self.name, "axj__jianxiong-discard::"..data.to.id)
      end
      room:throwCard(card, self.name, data.to, player)
    end
  end,
}
local huibian = fk.CreateTriggerSkill{
  name = "axj__huibian$",
  anim_type = "control",
  frequency = Skill.Compulsory,
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and
      table.find(player.room:getOtherPlayers(player), function(p)
        return p.kingdom == "wei"
      end)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    for _, p in ipairs(room:getOtherPlayers(player)) do
      if p.kingdom == "wei" then
        room:doIndicate(player.id, {p.id})
        room:addTableMark(player, self.name, p.id)
        player:control(p)
      end
    end
  end,

  refresh_events = {fk.AfterTurnEnd},
  can_refresh = function (self, event, target, player, data)
    return target == player and player:getMark(self.name) ~= 0
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    for _, id in ipairs(player:getMark(self.name)) do
      local p = room:getPlayerById(id)
      p:control(p)
    end
    room:setPlayerMark(player, self.name, 0)
  end,

  on_acquire = function (self, player, is_start)
    local room = player.room
    local turn_event = room.logic:getCurrentEvent():findParent(GameEvent.Turn, true)
    if turn_event and turn_event.data[1] == player and player:hasSkill(self) then
      for _, p in ipairs(room:getOtherPlayers(player)) do
        if p.kingdom == "wei" then
          room:doIndicate(player.id, {p.id})
          room:addTableMark(player, self.name, p.id)
          player:control(p)
        end
      end
    end
  end,
  on_lose = function (self, player, is_death)
    local room = player.room
    local turn_event = room.logic:getCurrentEvent():findParent(GameEvent.Turn, true)
    if turn_event and turn_event.data[1] == player and player:getMark(self.name) ~= 0 then
      for _, id in ipairs(player:getMark(self.name)) do
        local p = room:getPlayerById(id)
        p:control(p)
      end
    end
    room:setPlayerMark(player, self.name, 0)
  end,
}
caocao:addSkill(jianxiong)
caocao:addSkill(huibian)
Fk:loadTranslationTable{
  ["axj__caocao"] = "曹操",
  ["#axj__caocao"] = "怀天何焚",
  ["designer:axj__caocao"] = "白驹",
  ["illustrator:axj__caocao"] = "",
}
Fk:loadTranslationTable{
  ["axj__jianxiong"] = "奸雄",
  [":axj__jianxiong"] = "你造成或受到伤害后，可以令受到伤害角色获得造成伤害的牌，然后你可以摸一张牌或弃置其一张牌。",
  ["#axj__jianxiong-invoke"] = "奸雄：是否令 %dest 获得%arg，然后你摸一张牌或弃置其一张牌？",
  ["axj__jianxiong_discard"] = "弃置 %dest 一张牌",
  ["axj__jianxiong-discard"] = "奸雄：弃置 %dest 一张牌",
}
Fk:loadTranslationTable{
  ["axj__huibian"] = "挥鞭",
  [":axj__huibian"] = "主公技，你的回合内，魏势力角色由你控制。",
}

local simayi = General(extension, "axj__simayi", "wei", 3)
local langgu = fk.CreateTriggerSkill{
  name = "axj__langgu",
  anim_type = "control",
  events = {fk.Damage, fk.Damaged},
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) and data.from and not data.from.dead and not data.from:isNude() then
      if data.from == player then
        return #player:getCardIds("e") > 0 or #player.room:getOtherPlayers(player) > 0
      else
        return true
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local targets = table.map(room:getOtherPlayers(data.from), Util.IdMapper)
    if #data.from:getCardIds("e") > 0 then
      table.insert(targets, data.from.id)
    end
    local to = room:askForChoosePlayers(player, targets, 1, 1, "#axj__langgu-choose::"..data.from.id, self.name, true)
    if #to > 0 then
      self.cost_data = {tos = to}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(self.cost_data.tos[1])
    local flag = to == data.from and "e" or "he"
    local card = room:askForCardChosen(to, data.from, flag, self.name, "#axj__langgu-prey::"..data.from.id)
    room:moveCardTo(card, Card.PlayerHand, to, fk.ReasonPrey, self.name, nil, false, to.id)
    if to ~= player and not to.dead and not player.dead and not to:isNude() then
      room:doIndicate(player.id, {to.id})
      card = room:askForCardChosen(player, to, "he", self.name, "#axj__langgu-prey::"..to.id)
      room:moveCardTo(card, Card.PlayerHand, player, fk.ReasonPrey, self.name, nil, false, player.id)
    end
  end,
}
local yingshi = fk.CreateTriggerSkill{
  name = "axj__yingshi",
  anim_type = "control",
  events = {fk.AskForRetrial},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and
      (table.find(player.room:getOtherPlayers(player), function(p)
        return not p:isNude()
      end) or
      table.find(player:getCardIds("he"), function(id)
        return not player:prohibitResponse(Fk:getCardById(id))
      end))
  end,
  on_cost = function(self, event, target, player, data)
    local success, dat = player.room:askForUseActiveSkill(player, "axj__yingshi_active", "#axj__yingshi-invoke::"..target.id, true)
    if success and dat then
      self.cost_data = {tos = dat.targets, cards = dat.cards}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if #self.cost_data.cards > 0 then
      local card = Fk:getCardById(self.cost_data.cards[1])
      local resp = {
        from = player.id,
        card = card,
        skipDrop = true,
      }
      room:responseCard(resp)
      room:retrial(card, player, data, self.name, false)
    else
      local to = room:getPlayerById(self.cost_data.tos[1])
      local card = room:askForCardChosen(player, to, "he", self.name, "#axj__yingshi-retrial::"..target.id)
      local move = {
        ids = {card},
        from = to.id,
        toArea = Card.Processing,
        moveReason = fk.ReasonJustMove,
        skillName = self.name,
        proposer = player.id,
      }
      room:moveCards(move)
      data.card = Fk:getCardById(move.ids[1])
      room:sendLog{
        type = "#ChangedJudge",
        from = player.id,
        to = {target.id},
        card = {move.ids[1]},
        arg = self.name,
      }
      if not player.dead then
        room:damage{
          from = to,
          to = player,
          damage = 1,
          skillName = self.name,
        }
      end
    end
  end,
}
local yingshi_active = fk.CreateActiveSkill{
  name = "axj__yingshi_active",
  min_card_num = 0,
  max_card_num = 1,
  min_target_num = 0,
  max_target_num = 1,
  card_filter = function (self, to_select, selected)
    return #selected == 0 and not Self:prohibitResponse(Fk:getCardById(to_select))
  end,
  target_filter = function (self, to_select, selected, selected_cards)
    return #selected_cards == 0 and #selected == 0 and to_select ~= Self.id and
      not Fk:currentRoom():getPlayerById(to_select):isNude()
  end,
  feasible = function (self, selected, selected_cards)
    return #selected + #selected_cards == 1
  end,
}
local zhenxiu = fk.CreateTriggerSkill{
  name = "axj__zhenxiu",
  anim_type = "offensive",
  frequency = Skill.Limited,
  events = {fk.TurnEnd},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and player:usedSkillTimes(self.name, Player.HistoryGame) == 0
  end,
  on_use = function(self, event, target, player, data)
    player:gainAnExtraTurn(true)
  end,
}
local zhenxiu_delay = fk.CreateTriggerSkill{
  name = "#axj__zhenxiu_delay",
  anim_type = "control",
  events = {fk.TurnEnd},
  can_trigger = function(self, event, target, player, data)
    if target == player then
      local turn_event = player.room.logic:getCurrentEvent():findParent(GameEvent.Turn, true)
      return turn_event and turn_event.data[1] == player and turn_event.data[2].reason == "axj__zhenxiu"
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local tos = {}
    room.logic:getEventsOfScope(GameEvent.MoveCards, 1, function(e)
      for _, move in ipairs(e.data) do
        if move.to and move.toArea == Card.PlayerHand then
          table.insertIfNeed(tos, move.to)
        end
        if move.from then
          for _, info in ipairs(move.moveInfo) do
            if info.fromArea == Card.PlayerHand then
              table.insertIfNeed(tos, move.from)
            end
          end
        end
      end
    end, Player.HistoryTurn)
    room:sortPlayersByAction(tos)
    for _, id in ipairs(tos) do
      local p = room:getPlayerById(id)
      if not p.dead then
        p:turnOver()
      end
    end
  end,
}
simayi:addSkill(langgu)
Fk:addSkill(yingshi_active)
simayi:addSkill(yingshi)
zhenxiu:addRelatedSkill(zhenxiu_delay)
simayi:addSkill(zhenxiu)
Fk:loadTranslationTable{
  ["axj__simayi"] = "司马懿",
  ["#axj__simayi"] = "洛水无声",
  ["designer:axj__simayi"] = "白驹",
  ["illustrator:axj__simayi"] = "鬼画府",
}
Fk:loadTranslationTable{
  ["axj__langgu"] = "狼顾",
  [":axj__langgu"] = "你造成或受到伤害后，可以令一名角色获得伤害来源一张牌，若选择角色不为你，你获得其一张牌。",
  ["#axj__langgu-choose"] = "狼顾：你可以令一名角色获得 %dest 一张牌，若不为你，你获得其一张牌",
  ["#axj__langgu-prey"] = "狼顾：获得 %dest 一张牌",
}
Fk:loadTranslationTable{
  ["axj__yingshi"] = "鹰视",
  [":axj__yingshi"] = "一张判定牌生效前，你可打出一名角色一张牌代替之，若不为你的牌，你受到其造成的一点伤害。",
  ["axj__yingshi_active"] = "鹰视",
  ["#axj__yingshi-invoke"] = "鹰视：打出一张牌，或选择一名角色的一张牌，修改 %dest 的判定",
  ["#axj__yingshi-retrial"] = "鹰视：打出 %dest 的一张牌修改判定",
}
Fk:loadTranslationTable{
  ["axj__zhenxiu"] = "震朽",
  [":axj__zhenxiu"] = "限定技，回合结束后，你可以执行一个额外回合，期间手牌数变化过的角色于回合结束后依次翻面。",
  ["#axj__zhenxiu_delay"] = "震朽",
}

local xiahoudun = General(extension, "axj__xiahoudun", "wei", 4)
local ganglie = fk.CreateTriggerSkill{
  name = "axj__ganglie",
  anim_type = "masochism",
  events = {fk.EventPhaseStart, fk.Damaged},
  can_trigger = function (self, event, target, player, data)
    if target == player and player:hasSkill(self) then
      if event == fk.EventPhaseStart then
        return player.phase == Player.Start
      elseif event == fk.Damaged then
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local judge = {
      who = player,
      reason = self.name,
      pattern = ".|.|^heart",
    }
    room:judge(judge)
    if judge.card.suit == Card.Heart then return end
    local from
    room.logic:getActualDamageEvents(1, function (e)
      local damage = e.data[1]
      if damage.to == player and damage.from then
        from = damage.from
        return true
      end
    end, nil, 1)
    if from == nil or from.dead then return end
    room:doIndicate(player.id, {from.id})
    room:damage{
      from = player,
      to = from,
      damage = 1,
      skillName = self.name,
    }
    if from.dead or from:getHandcardNum() < 2 then return end
    if #room:askForDiscard(from, 2, 2, false, self.name, true, nil, "#axj__ganglie-discard") == 2 and
      from:isWounded() and not from.dead then
      room:recover{
        who = from,
        num = 1,
        recoverBy = from,
        skillName = self.name,
      }
    end
  end,
}
local fuxue = fk.CreateTriggerSkill{
  name = "axj__fuxue",
  anim_type = "support",
  events = {fk.Deathed},
  can_trigger = function (self, event, target, player, data)
    if player.dead then
      local record = player.room:getBanner(self.name)
      for _, info in ipairs(record) do
        if info.from == target.id and info.victim == player.id then
          return true
        end
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local record = room:getBanner(self.name) or {}
    for i = #record, 1, -1 do
      if record[i].victim == player.id then
        table.remove(record, i)
      end
    end
    room:setBanner(self.name, record)
    room:revivePlayer(player, true, self.name)
  end,

  refresh_events = {fk.Death},
  can_refresh = function (self, event, target, player, data)
    return target == player and player:hasSkill(self, true, true) and data.damage and data.damage.from
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    local record = room:getBanner(self.name) or {}
    table.insert(record, {
      from = data.damage.from.id,
      victim = player.id,
    })
    room:setBanner(self.name, record)
  end,
}
xiahoudun:addSkill(ganglie)
xiahoudun:addSkill(fuxue)
Fk:loadTranslationTable{
  ["axj__xiahoudun"] = "夏侯惇",
  ["#axj__xiahoudun"] = "苍心蕴烈",
  ["designer:axj__xiahoudun"] = "白驹",
  ["illustrator:axj__xiahoudun"] = "凡果",
}
Fk:loadTranslationTable{
  ["axj__ganglie"] = "刚烈",
  [":axj__ganglie"] = "准备阶段或你受到伤害后，你可以判定，若判定结果不为<font color='red'>♥</font>，你对上次对你造成伤害的角色造成一点伤害，"..
  "然后其可以弃置两张手牌并回复一点体力。",
  ["#axj__ganglie-discard"] = "刚烈：你可以弃置两张手牌，回复1点体力",
}
Fk:loadTranslationTable{
  ["axj__fuxue"] = "复血",
  [":axj__fuxue"] = "杀死你的角色死亡后，你重新加入游戏。",
}

local zhangliao = General(extension, "axj__zhangliao", "wei", 4)
local tuxi = fk.CreateTriggerSkill{
  name = "axj__tuxi",
  mute = true,
  events = {fk.DrawNCards, fk.EventPhaseProceeding},
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) then
      if event == fk.DrawNCards then
        return data.n > 0
      elseif event == fk.EventPhaseProceeding then
        return player.phase == Player.Discard and not player:isKongcheng() and player:getMaxCards() > 0
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if event == fk.DrawNCards then
      local choices = {}
      for i = 1, data.n, 1 do
        table.insert(choices, tostring(i))
      end
      table.insert(choices, "Cancel")
      local choice = room:askForChoice(player, choices, self.name, "#axj__tuxi-choice")
      if choice ~= "Cancel" then
        self.cost_data = {choice = choice}
        return true
      end
    elseif event == fk.EventPhaseProceeding then
      local n = math.max(player:getHandcardNum() - player:getMaxCards(), 0)
      local cards = room:askForDiscard(player, n + 1, 999, false, self.name, true, nil, "#axj__tuxi-discard:::"..n, true)
      if #cards > n then
        self.cost_data = {cards = cards, choice = #cards - n}
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(self.name)
    local n = tonumber(self.cost_data.choice)
    if event == fk.DrawNCards then
      room:notifySkillInvoked(player, self.name, "control")
      data.n = data.n - n
    else
      room:notifySkillInvoked(player, self.name, "offensive")
      player._phase_end = true
      room:throwCard(self.cost_data.cards, self.name, player, player)
      if player.dead then return end
    end
    local targets = table.map(room.alive_players, Util.IdMapper)
    local name = event == fk.DrawNCards and "snatch" or "slash"
    for i = 1, n, 1 do
      if player.dead then return end
      local use = U.askForUseVirtualCard(room, player, name, nil, self.name,
        "#axj__tuxi-use:::"..(n - i + 1)..":"..name, true, true, true, true, {exclusive_targets = targets}, true)
      if use then
        for j = #targets, 1, -1 do
          if table.contains(TargetGroup:getRealTargets(use.tos), targets[j]) then
            table.remove(targets, j)
          end
        end
        room:useCard(use)
      else
        break
      end
    end
  end,
}
local zhiti = fk.CreateTriggerSkill{
  name = "axj__zhiti",
  anim_type = "control",
  events = {fk.BeforeCardsMove},
  can_trigger = function(self, event, target, player, data)
    if not player:hasSkill(self) then return end
    local phase_event = player.room.logic:getCurrentEvent():findParent(GameEvent.Phase, true)
    if phase_event == nil then return end
    local to = phase_event.data[1]
    if to.phase ~= Player.Play or not player:inMyAttackRange(to) or to.dead then return end
    for _, move in ipairs(data) do
      if move.to == to.id and move.toArea == Card.PlayerHand and #move.moveInfo > 0 then
        return true
      end
    end
  end,
  on_cost = function (self, event, target, player, data)
    local room = player.room
    if room:askForSkillInvoke(player, self.name, nil, "#axj__zhiti-invoke::"..room.current.id) then
      self.cost_data = {tos = {room.current.id}}
      return true
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local phase_event = room.logic:getCurrentEvent():findParent(GameEvent.Phase, true)
    if phase_event == nil then return end
    local to = phase_event.data[1]
    if to.phase ~= Player.Play or not player:inMyAttackRange(to) or to.dead then return end
    local record = player:getTableMark(self.name)
    local mirror_moves = {}
    for _, move in ipairs(data) do
      if move.to and move.toArea == Card.PlayerHand then
        local mirror_info = move.moveInfo
        if #mirror_info > 0 then
          local ids = record[string.format("%.0f", move.to)] or {}
          for _, info in ipairs(mirror_info) do
            table.insertIfNeed(ids, info.cardId)
          end
          record[string.format("%.0f", move.to)] = ids
          move.moveInfo = {}
          local mirror_move = table.clone(move)
          mirror_move.toArea = Card.PlayerSpecial
          mirror_move.specialName = "$axj__zhiti"
          mirror_move.visible = move.visible
          mirror_move.moveMark = nil
          mirror_move.moveInfo = mirror_info
          table.insert(mirror_moves, mirror_move)
        end
      end
    end
    table.insertTable(data, mirror_moves)
    room:setPlayerMark(player, self.name, record)
  end,
}
local zhiti_delay = fk.CreateTriggerSkill{
  name = "#axj__zhiti_delay",
  mute = true,
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:getMark("axj__zhiti") ~= 0
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local dat = table.simpleClone(player:getMark("axj__zhiti"))
    room:setPlayerMark(player, "axj__zhiti", 0)
    local moves = {}
    for _, p in ipairs(room:getOtherPlayers(player)) do
      local ids = dat[string.format("%.0f", p.id)] or {}
      ids = table.filter(ids, function (id)
        return table.contains(p:getPile("$axj__zhiti"), id)
      end)
      if #ids > 0 then
        table.insert(moves, {
          ids = ids,
          from = p.id,
          to = p.id,
          toArea = Card.PlayerHand,
          moveReason = fk.ReasonJustMove,
          skillName = "axj__zhiti",
        })
      end
    end
    if #moves > 0 then
      room:moveCards(table.unpack(moves))
    end
  end,
}
zhiti:addRelatedSkill(zhiti_delay)
zhangliao:addSkill(tuxi)
zhangliao:addSkill(zhiti)
Fk:loadTranslationTable{
  ["axj__zhangliao"] = "张辽",
  ["#axj__zhangliao"] = "垂翼风威",
  ["designer:axj__zhangliao"] = "白驹",
  ["illustrator:axj__zhangliao"] = "张帅",
}
Fk:loadTranslationTable{
  ["axj__tuxi"] = "突袭",
  [":axj__tuxi"] = "摸牌/弃牌阶段，你可以少摸/多弃任意张牌并依次视为使用等量张【顺手牵羊】/【杀】且无距离限制、目标须各不同。",
  ["#axj__tuxi-choice"] = "突袭：你可以少摸任意张牌，视为使用等量无距离限制、目标各不相同的【顺手牵羊】",
  ["#axj__tuxi-discard"] = "突袭：你可以多弃任意张牌，视为使用等量无距离限制、目标各不相同的【杀】（弃牌阶段需弃%arg张）",
  ["#axj__tuxi-use"] = "突袭：视为使用【%arg2】（还剩%arg张！）",
}
Fk:loadTranslationTable{
  ["axj__zhiti"] = "止啼",
  [":axj__zhiti"] = "你攻击范围的角色于其出牌阶段获得牌时，你可以令其延至你回合开始时再获得。",
  ["#axj__zhiti-invoke"] = "止啼：%dest 即将获得牌，是否令其延后至你回合开始再获得？",
  ["$axj__zhiti"] = "止啼",
  ["#axj__zhiti_delay"] = "止啼",
}

local liubei = General(extension, "axj__liubei", "shu", 4)
local renwang = fk.CreateViewAsSkill{
  name = "axj__renwang",
  pattern = ".|.|.|.|.|basic",
  prompt = "#axj__renwang",
  interaction = function(self)
    local all_names = U.getAllCardNames("b")
    return U.CardNameBox {
      choices = U.getViewAsCardNames(Self, self.name, all_names, nil, Self:getTableMark("axj__renwang-round")),
      all_choices = all_names,
    }
  end,
  card_filter = Util.FalseFunc,
  view_as = function(self, cards)
    if self.interaction.data == nil then return end
    local card = Fk:cloneCard(self.interaction.data)
    card.skillName = self.name
    return card
  end,
  before_use = function(self, player, use)
    local room = player.room
    room:addTableMark(player, "axj__renwang-round", use.card.trueName)
    room:askForYiji(player, player:getCardIds("he"), room:getOtherPlayers(player), self.name, 2, 999, "#axj__renwang-give")
  end,
  enabled_at_play = function(self, player)
    return #player:getCardIds("he") > 1 and #Fk:currentRoom().alive_players > 1
  end,
  enabled_at_response = function(self, player, response)
    return #player:getCardIds("he") > 1 and #Fk:currentRoom().alive_players > 1 and
      #U.getViewAsCardNames(player, self.name, U.getAllCardNames("b"), nil, player:getTableMark("axj__renwang-round")) > 0
  end,
}
local juyil = fk.CreateTriggerSkill{
  name = "axj__juyil$",
  anim_type = "control",
  frequency = Skill.Compulsory,

  on_acquire = function (self, player, is_start)
    local room = player.room
    if player:hasSkill(self) then
      for _, p in ipairs(room.players) do
        if p.role == "renegade" then
          p.role = "loyalist"
          room:broadcastProperty(p, "role")
        end
      end
    end
  end,
}
liubei:addSkill(renwang)
liubei:addSkill(juyil)
Fk:loadTranslationTable{
  ["axj__liubei"] = "刘备",
  ["#axj__liubei"] = "汉炬之执",
  ["designer:axj__liubei"] = "白驹",
  ["illustrator:axj__liubei"] = "",
}
Fk:loadTranslationTable{
  ["axj__renwang"] = "仁望",
  [":axj__renwang"] = "每轮每牌名限一次，你需使用或打出基本牌时，可以分配至少两张牌给其他角色，视为使用或打出之。",
  ["#axj__renwang"] = "仁望：选择视为使用或打出的基本牌和目标，然后分配至少两张牌视为使用或打出之",
  ["#axj__renwang-give"] = "仁望：将至少两张牌分配给其他角色",
}
Fk:loadTranslationTable{
  ["axj__juyil"] = "聚义",
  [":axj__juyil"] = "主公技，本局游戏的内奸改为忠臣。",
}

local guanyu = General(extension, "axj__guanyu", "shu", 4)
local wusheng = fk.CreateViewAsSkill{
  name = "axj__wusheng",
  pattern = ".",
  anim_type = "offensive",
  prompt = "#axj__wusheng",
  interaction = function(self)
    local all_names = U.getAllCardNames("bt")
    local names = table.filter(U.getViewAsCardNames(Self, self.name, all_names), function (name)
      return Fk:cloneCard(name).is_damage_card
    end)
    if #names == 0 then return end
    return U.CardNameBox {choices = names, all_choices = all_names}
  end,
  card_filter = function(self, to_select, selected)
    if #selected == 0 and self.interaction.data and Fk:getCardById(to_select).color == Card.Red then
      if Fk:cloneCard(self.interaction.data).trueName == "slash" then
        return true
      else
        return Fk:getCardById(to_select).trueName == "slash"
      end
    end
  end,
  view_as = function(self, cards)
    if #cards ~= 1 or not self.interaction.data then return end
    local card = Fk:cloneCard(self.interaction.data)
    card:addSubcard(cards[1])
    card.skillName = self.name
    return card
  end,
  enabled_at_response = function (self, player, response)
    if response then return end
    local all_names = U.getAllCardNames("bt")
    return #table.filter(U.getViewAsCardNames(Self, self.name, all_names), function (name)
      return Fk:cloneCard(name).is_damage_card
    end) > 0
  end,
}
local yijue = fk.CreateTriggerSkill{
  name = "axj__yijue",
  switch_skill_name = "axj__yijue",
  anim_type = "switch",
  frequency = Skill.Compulsory,
  events = {fk.DamageInflicted, fk.DamageCaused},
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) then
      if event == fk.DamageInflicted and player:getSwitchSkillState(self.name) == fk.SwitchYang then
        return data.damage >= player.hp + player.shield
      elseif event == fk.DamageCaused and player:getSwitchSkillState(self.name) == fk.SwitchYin then
        return data.damage >= data.to.hp + data.to.shield
      end
    end
  end,
  on_use = Util.TrueFunc,
}
guanyu:addSkill(wusheng)
guanyu:addSkill(yijue)
Fk:loadTranslationTable{
  ["axj__guanyu"] = "关羽",
  ["#axj__guanyu"] = "刀卷云横",
  ["designer:axj__guanyu"] = "Kane&伶",
  ["illustrator:axj__guanyu"] = "太玄工作室",
}
Fk:loadTranslationTable{
  ["axj__wusheng"] = "武圣",
  [":axj__wusheng"] = "你可以将红色牌当任意伤害牌使用，且其中有一张牌牌名须为【杀】。",
  ["#axj__wusheng"] = "武圣：将红色牌当任意伤害牌使用，其中一张牌名须为【杀】",
}
Fk:loadTranslationTable{
  ["axj__yijue"] = "义绝",
  [":axj__yijue"] = "转换技，锁定技，当你①受到②造成致命伤害时，防止之。",
}

--local zhangfei = General(extension, "axj__zhangfei", "shu", 4)
Fk:loadTranslationTable{
  ["axj__zhangfei"] = "张飞",
  ["#axj__zhangfei"] = "万军夺气",
  ["designer:axj__zhangfei"] = "杨林&白驹",
  ["illustrator:axj__zhangfei"] = "太玄工作室",

  ["axj__paoxiao"] = "咆哮",
  [":axj__paoxiao"] = "你的手牌数于一名角色的出牌阶段变化后，可以令其此阶段使用【杀】的次数上限+1，则若此阶段结束时若使用【杀】至上限，"..
  "你摸一张牌，否则你视为对其使用【杀】。",
}
Fk:loadTranslationTable{
  ["axj__tishen"] = "替身",
  [":axj__tishen"] = "限定技，轮次开始时，你可以于已死亡角色座次上依次选将并令之以1体力上限无手牌登场，本轮这些角色由你控制且于轮次结束时死亡。",
}

local machao = General(extension, "axj__machao", "shu", 4)
local tieji = fk.CreateTriggerSkill{
  name = "axj__tieji",
  switch_skill_name = "axj__tieji",
  anim_type = "switch",
  events = {fk.TargetSpecifying, fk.DamageCaused},
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) and data.card and data.card.trueName == "slash" then
      if event == fk.TargetSpecifying then
        return player:getSwitchSkillState(self.name) == fk.SwitchYang
      elseif event == fk.DamageCaused then
        return player:getSwitchSkillState(self.name) == fk.SwitchYin
      end
    end
  end,
  on_cost = function (self, event, target, player, data)
    local room = player.room
    local choices = {}
    local n, to
    if event == fk.TargetSpecifying then
      n = 1
      to = room:getPlayerById(data.to)
    elseif event == fk.DamageCaused then
      n = 2
      to = data.to
    end
    table.insert(choices, "draw"..n)
    if (to ~= player and not to:isNude()) or
      (to == player and table.find(player:getCardIds("he"), function (id)
        return not player:prohibitDiscard(id)
      end)) then
      table.insert(choices, "axj__tieji_discard::"..to.id..":"..n)
    end
    for _, s in ipairs(to.player_skills) do
      if s:isPlayerSkill(to) and s.visible and to:hasSkill(s) then
        table.insert(choices, "axj__tieji_invalidate::"..to.id..":"..n)
        break
      end
    end
    table.insert(choices, "Cancel")
    local choice = room:askForChoice(player, choices, self.name)
    if choice ~= "Cancel" then
      self.cost_data = {tos = {to.id}, choice = choice}
      return true
    end
  end,
  on_use  = function (self, event, target, player, data)
    local room = player.room
    local n = event == fk.TargetSpecifying and 1 or 2
    local to = event == fk.TargetSpecifying and room:getPlayerById(data.to) or data.to
    local choice = self.cost_data.choice
    if choice:startsWith("draw") then
      player:drawCards(n, self.name)
    elseif choice:startsWith("axj__tieji_discard") then
      if to == player then
        room:askForDiscard(player, n, n, true, self.name, false, nil, "#axj__tieji-discard::"..to.id..":"..n)
      else
        if #to:getCardIds("he") <= n then
          room:throwCard(to:getCardIds("he"), self.name, to, player)
        else
          local cards = room:askForCardsChosen(player, to, n, n, "he", self.name, "#axj__tieji-discard::"..to.id..":"..n)
          room:throwCard(cards, self.name, to, player)
        end
      end
    elseif choice:startsWith("axj__tieji_invalidate") then
      local skills = table.filter(to.player_skills, function (s)
        return s:isPlayerSkill(to) and s.visible and to:hasSkill(s)
      end)
      skills = table.map(skills, function (s)
        return s.name
      end)
      if #skills > n then
        skills = room:askForChoices(player, skills, n, n, self.name, "#axj__tieji-invalidate::"..to.id..":"..n, false, true)
      end
      for _, s in ipairs(skills) do
        room:invalidateSkill(to, s, "-turn")
      end
    end
  end,
}
local huima = fk.CreateViewAsSkill{
  name = "axj__huima",
  switch_skill_name = "axj__huima",
  anim_type = "switch",
  pattern = "slash",
  prompt = function (self, selected_cards, selected)
    return "#axj__huima-"..Self:getSwitchSkillState(self.name, false, true)
  end,
  card_filter = Util.FalseFunc,
  view_as = function(self, cards)
    local card = Fk:cloneCard("slash")
    card.skillName = self.name
    return card
  end,
  before_use = function (self, player, use)
    player:addSkillUseHistory("axj__tieji", 1)
    player.room:setPlayerMark(player, MarkEnum.SwithSkillPreName.."axj__tieji", player:getSwitchSkillState("axj__tieji", true))
  end,
  enabled_at_play = function (self, player)
    return player:hasSkill("axj__tieji", true) and player:usedSkillTimes(self.name, Player.HistoryTurn) == 0
  end,
  enabled_at_response = function (self, player, response)
    return not response and player:hasSkill("axj__tieji", true) and player:usedSkillTimes(self.name, Player.HistoryTurn) == 0
  end,
}
local huima_prohibit = fk.CreateProhibitSkill{
  name = "#axj__huima_prohibit",
  is_prohibited = function(self, from, to, card)
    if table.contains(card.skillNames, "axj__huima") then
      if from:getSwitchSkillState("axj__huima") == fk.SwitchYang then
        return not from:inMyAttackRange(to)
      elseif from:getSwitchSkillState("axj__huima") == fk.SwitchYin then
        return from:inMyAttackRange(to)
      end
    end
  end,
}
local huima_targetmod = fk.CreateTargetModSkill{
  name = "#axj__huima_targetmod",
  bypass_distances = function(self, player, skill, card)
    return skill.trueName == "slash_skill" and card and table.contains(card.skillNames, "axj__huima") and
      player:getSwitchSkillState("axj__huima") == fk.SwitchYin
  end,
}
huima:addRelatedSkill(huima_prohibit)
huima:addRelatedSkill(huima_targetmod)
machao:addSkill(tieji)
machao:addSkill(huima)
Fk:loadTranslationTable{
  ["axj__machao"] = "马超",
  ["#axj__machao"] = "风扬猊骑",
  ["designer:axj__machao"] = "白驹",
  ["illustrator:axj__machao"] = "Asker",
}
Fk:loadTranslationTable{
  ["axj__tieji"] = "铁骑",
  [":axj__tieji"] = "转换技，你使用【杀】①指定目标②造成伤害时，你可以选择一项（X为当前序号数）：1.摸X张牌；2.弃置对方X张牌："..
  "3.令对方X个技能本回合无效。",
  ["axj__tieji_discard"] = "弃置%dest%arg张牌",
  ["axj__tieji_invalidate"] = "令%dest%arg个技能本回合失效",
  ["#axj__tieji-discard"] = "铁骑：弃置 %dest %arg张牌",
  ["#axj__tieji-invalidate"] = "铁骑：令 %dest %arg个技能本回合失效",
}
Fk:loadTranslationTable{
  ["axj__huima"] = "回马",
  [":axj__huima"] = "转换技，每回合限一次，当你需使用【杀】时，可以指定攻击范围①内②外的目标，然后转换“铁骑”以视为使用之。",
  ["#axj__huima-yang"] = "回马：转换“铁骑”，视为对攻击范围内的目标使用【杀】",
  ["#axj__huima-yin"] = "回马：转换“铁骑”，视为对攻击范围外的目标使用【杀】",
}

local sunquan = General(extension, "axj__sunquan", "wu", 4)
local zhiheng = fk.CreateActiveSkill{
  name = "axj__zhiheng",
  anim_type = "drawcard",
  target_num = 0,
  min_card_num = 1,
  max_card_num = 4,
  prompt = "#axj__zhiheng",
  can_use = function(self, player)
    return #player:getTableMark("axj__zhiheng-phase") < 4
  end,
  card_filter = function(self, to_select, selected)
    return #selected < 4 and not Self:prohibitDiscard(Fk:getCardById(to_select))
  end,
  feasible = function (self, selected, selected_cards)
    if #selected == 0 and #selected_cards < 5 and #selected_cards > 0 and
      not table.contains(Self:getTableMark("axj__zhiheng-phase"), #selected_cards) then
      if not table.find(Fk:currentRoom().alive_players, function (p)
        return p.hp == #selected_cards
      end) then
        return table.find(Fk:currentRoom().alive_players, function(p)
          return table.find(Fk:currentRoom().alive_players, function(q)
            return p ~= q and p:canMoveCardsInBoardTo(q)
          end) ~= nil
        end)
      else
        return true
      end
    end
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    room:addTableMark(player, "axj__zhiheng-phase", #effect.cards)
    local yes = table.find(room.alive_players, function (p)
      return p.hp == #effect.cards
    end)
    room:throwCard(effect.cards, self.name, player, player)
    if player.dead then return end
    if yes then
      player:drawCards(#effect.cards, self.name)
    else
      if #room:canMoveCardInBoard() > 0 then
        local targets = room:askForChooseToMoveCardInBoard(player, "#axj__zhiheng-move", self.name, false)
        targets = table.map(targets, function(id) return room:getPlayerById(id) end)
        room:askForMoveCardInBoard(player, targets[1], targets[2], self.name)
      end
    end
  end,
}
local bingchen = fk.CreateTriggerSkill{
  name = "axj__bingchen$",
  anim_type = "control",
  events = {fk.GameStart},
  can_trigger = function (self, event, target, player, data)
    return player:hasSkill(self)
  end,
  on_cost = function (self, event, target, player, data)
    local room = player.room
    local to = room:askForChoosePlayers(player, table.map(room.alive_players, Util.IdMapper), 1, 1,
      "#axj__bingchen-choose", self.name, true)
    if #to > 0 then
      self.cost_data = {tos = to}
      return true
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(self.cost_data.tos[1])
    local all_generals = room:getNGenerals(room.settings.generalNum)
    local n = room.settings.enableDeputy and 2 or 1
    local generals = room:askForGeneral(to, all_generals, n)
    local general, deputy = "", ""
    if type(generals) == "table" then
      general, deputy = generals[1], generals[2]
    else
      general = generals
      generals = {general}
    end
    all_generals = table.filter(all_generals, function(g) return not table.contains(generals, g) end)
    room:returnToGeneralPile(all_generals)
    room:returnToGeneralPile({to.general})
    if to.deputyGeneral ~= "" then
      room:returnToGeneralPile({to.deputyGeneral})
    end
    room:changeHero(to, general, false, false, false, true, true)
    if deputy ~= "" then
      room:changeHero(to, deputy, false, true, false, true, false)
    end
  end,
}
sunquan:addSkill(zhiheng)
sunquan:addSkill(bingchen)
Fk:loadTranslationTable{
  ["axj__sunquan"] = "孙权",
  ["#axj__sunquan"] = "定鼎稳江",
  ["designer:axj__sunquan"] = "白驹",
  ["illustrator:axj__sunquan"] = "",
}
Fk:loadTranslationTable{
  ["axj__zhiheng"] = "制衡",
  [":axj__zhiheng"] = "出牌阶段各限一次，你可弃置一/二/三/四张牌并摸等量牌。若场上没有对应项体力的角色，此项效果改为移动场上一张牌。",
  ["#axj__zhiheng"] = "制衡：弃置至多四张牌并摸等量牌，若场上没有此体力值角色则改为移动场上一张牌",
  ["#axj__zhiheng-move"] = "制衡：请移动场上一张牌",
}
Fk:loadTranslationTable{
  ["axj__bingchen"] = "炳臣",
  [":axj__bingchen"] = "主公技，游戏开始时，你可令一名角色换将。",
  ["#axj__bingchen-choose"] = "炳臣：你可令一名角色换将",
}

return extension
